from django.db import transaction
from rest_framework import serializers

from goods.models import SKUImage, SKU, SKUSpecification, GoodsCategory,SPU, SpecificationOption, SPUSpecification
from meiduo_mall.utils.fdfs.storage import FDFSStorage


class SKUImageSerializer(serializers.ModelSerializer):
    # 定义商品图片序列化器类

    sku = serializers.StringRelatedField(label='sku商品名称')
    # 创建一个sku_id 字段
    sku_id = serializers.IntegerField(label='SKU商品ID')

    class Meta:
        model = SKUImage
        exclude = ('create_time', 'update_time')

    # 添加图片 调用 校验sku_id 是否存在
    def validate_sku_id(self,value):

        try:
            sku = SKU.objects.get(id=value)

        except SKU.DoesNotExist:
            raise serializers.ValidationError('sku 不存在')

        return sku

    # 原有的方法不满足
    def create(self, validated_data):
        # 获取上传图片
        filed = validated_data['image']
        print(filed)

        # 调用图片保存方法
        fdfs = FDFSStorage()

        try:
            fdfs_id = fdfs.save(filed.name,filed)
        except Exception:
            raise serializers.ValidationError('FDFS 上传失败')

        sku = validated_data['sku_id']

        sku_image = SKUImage.objects.create(
            sku= sku,
            image = fdfs_id
        )

        if not sku.default_image:
            sku.default_image = sku_image.image.url

            sku.save()

            # 当新增了商品SKU图片时，异步生成新的商品详情页面
            # from celery_tasks.html.tasks import generate_static_sku_detail_html
            # generate_static_sku_detail_html.delay(sku.id)

        return sku_image

    # 重写修改图片方法
    def update(self, instance, validated_data):

        filed = validated_data['image']

        fdfs = FDFSStorage()

        try:
            fdfs_id = fdfs.save(filed.name, filed)
        except Exception:
            raise serializers.ValidationError('FDFS上传失败')
        # print(instance.image)
        # print('----------------------------------------------------')
        instance.image = fdfs_id
        # print(instance.image)
        instance.save()

        return instance


class SKUSimpleSerializer(serializers.ModelSerializer):
    # 简单SKU商品序列化器类

    class Meta:
        model = SKU
        fields = ('id','name')


class SKUSpecSerializer(serializers.ModelSerializer):
    # 商品规格详情序列化器类

    spec_id = serializers.IntegerField(label='规格id')
    option_id = serializers.IntegerField(label='选项id')

    class Meta:
        model = SKUSpecification
        fields = ('spec_id', 'option_id')


class SKUSerializer(serializers.ModelSerializer):
    # 定义商品SKU序列化器类

    spu = serializers.StringRelatedField(label='SPU商品名称')
    category = serializers.StringRelatedField(label='三级商品分类名称')

    spu_id = serializers.IntegerField(label='spu id')
    category_id = serializers.IntegerField(label='三级分类组id')

    # 指定序列化器类关联序列化
    specs = SKUSpecSerializer(label='商品规格信息', many=True)

    class Meta:
        model = SKU
        exclude = ('create_time', 'update_time', 'default_image')

    def validate(self, attrs):
        # 三级分类id
        category_id = attrs['category_id']
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            raise serializers.ValidationError('三级分类不存在')

        # spu 校验
        spu_id = attrs['spu_id']
        try:
            spu = SPU.objects.get(id=spu_id)
        except SPU.DoesNotExist:
            raise serializers.ValidationError('spu商品不存在')

        # 校验spu商品三级分类与 category_id 是否相同
        if spu.category3_id != category_id:
            raise serializers.ValidationError('商品分类信息错误')

        # 检查SPU规格是否有效
        spu_specs = spu.specs.all()  # 商品规格选项 如 颜色 内存版本 屏幕大小
        spec_count = spu_specs.count()  # 规格项目总数量
        print(spec_count)

        specs = attrs['specs']  # 用户输入的规格数据 是一个字典或者类字典

        if spec_count > len(specs):
            raise serializers.ValidationError('SKU规格数据不完整')


        # spec_count_ids = [spec.id for spec in spu_specs].sort()  # 商品规格选项数字 列表
        spec_count_ids = [spec.id for spec in spu_specs]  # 商品规格选项数字 列表
        specs_ids = [spec.get('spec_id') for spec in specs]  # 用户输入的规格选项列表

        if spec_count_ids.sort() != specs_ids.sort():
            raise serializers.ValidationError('商品规格数据错误')

        for spec in specs:
            spec_id = spec['spec_id']
            option_id = spec['option_id']

            options = SpecificationOption.objects.filter(spec_id=spec_id)
            options_ids = [option.id for option in options]

            if option_id not in options_ids:
                raise serializers.ValidationError('规格选项错误')
        return attrs

    # SKU.objects.create(**validated_data)
    def create(self,validated_data):
        """保存SPU商品数据"""
        specs = validated_data.pop('specs')

        with transaction.atomic():  # 使用事物 即必选全部完成 否则回滚

            # sku = super().create(validated_data)  # 调用父类方法保存数据
            sku = SKU.objects.create(**validated_data)

            for spec in specs:
                SKUSpecification.objects.create(
                    sku=sku,
                    spec_id=spec.get('spec_id'),
                    option_id=spec.get('option_id')
                    )

        return sku

    def update(self,instance, validated_data):

        specs = validated_data.pop('specs')

        # 获取sku商品的规格信息
        sku_specs = [{
            'spec_id': spec.spec_id,
            'option_id': spec.option_id
        } for spec in instance.specs.all()]

        # 调用事物
        with transaction.atomic():
            sku = super().update(instance,validated_data)

            if specs != sku_specs:  # 商品规格信息不一致 删除原有规格
                # 清除sku原有的规格信息
                sku.specs.all().delete()
                for spec in specs:
                    SKUSpecification.objects.create(
                        sku=sku,
                        spec_id=spec.get('spec_id'),
                        option_id=spec.get('option_id')
                    )
        return sku


class CategorySimpleSerializer(serializers.ModelSerializer):
    # 分类序列化器类

    class Meta:
        model = GoodsCategory
        fields = ('id', 'name')


class SPUSimpleSerializer(serializers.ModelSerializer):
    # 简单的商品展示
    class Meta:
        model = SPU
        fields = ('id', 'name')


class SpecOptionSerializer(serializers.ModelSerializer):
    """SPU规格序列化器类"""
    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


class SPUSpecSerializer(serializers.ModelSerializer):
    """SPU序列化器类"""
    # 关联对象的嵌套序列化
    spu = serializers.StringRelatedField(label='SPU名称')
    spu_id = serializers.IntegerField(label='SPU ID')

    # 关联对象的嵌套序列化
    options = SpecOptionSerializer(label='Opt选项', many=True)

    class Meta:
        model = SPUSpecification
        fields = ('id', 'name', 'spu', 'spu_id', 'options')



